package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.lang.StringUtils;
import com.binary.core.util.BinaryUtils;
import com.binary.framework.exception.ServiceException;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.EamArtifactElement;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.comm.model.es.EamDiagramRelease;
import com.uinnova.product.eam.comm.model.es.EamMultiModelHierarchy;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.model.ArtifactConstraintVo;
import com.uinnova.product.eam.model.EamArtifactCiVo;
import com.uinnova.product.eam.model.EamArtifactElementVo;
import com.uinnova.product.eam.model.asset.EamReleaseHistoryDTO;
import com.uinnova.product.eam.model.dto.EamHierarchyDto;
import com.uinnova.product.eam.model.dto.ElementDto;
import com.uinnova.product.eam.model.enums.ArtifactRelation;
import com.uinnova.product.eam.model.enums.ArtifactType;
import com.uinnova.product.eam.model.vo.*;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.vmdb.comm.model.ci.CCcCi;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.comm.model.ci.CcCiClass;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.product.vmdb.provider.rlt.bean.CcCiRltInfo;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.diagram.EamDiagramQuery;
import com.uinnova.project.base.diagram.comm.model.*;
import com.uinnova.project.db.eam.ESDiagramDao;
import com.uino.api.client.cmdb.ICIClassApiSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.cmdb.query.ESRltSearchBean;
import com.uino.bean.permission.base.SysRole;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.business.UserInfo;
import com.uino.bean.permission.query.CSysUser;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 业务建模视图处理业务层
 *
 * @author ch
 * @date 2021/11/3
 */
@Service
@Slf4j
public class BmDiagramSvcImpl implements BmDiagramSvc {

    @Autowired
    private ESDiagramApiClient diagramApiClient;
    @Autowired
    private IUserApiSvc userApiSvc;
    @Autowired
    private IEamArtifactColumnSvc artifactSvc;
    @Autowired
    private IamsCIRltSwitchSvc ciRltSwitchSvc;
    @Resource
    private ICISwitchSvc ciSwitchSvc;
    @Autowired
    private ICIClassApiSvc iciClassApiSvc;
    @Autowired
    private ESDiagramDao esDiagramDao;
    @Resource
    private BmConfigSvc bmConfigSvc;
    @Autowired
    private IBmHierarchySvc bmHierarchySvc;
    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    private IBmMultiModelHierarchySvc hierarchySvc;

    @Override
    public boolean handlerRelease(String energy) {
        ESDiagram esDiagram = diagramApiClient.getEsDiagram(energy, 0);
        if (esDiagram == null) {
            throw new ServiceException("获取视图错误!");
        }
        if (!BinaryUtils.isEmpty(esDiagram.getOwnerCode()) && !SysUtil.getCurrentUserInfo().getLoginCode().equals(esDiagram.getOwnerCode())) {
            throw new ServiceException("非视图拥有者无发布权限!");
        }
        // 没有发布过得数据不弹框
        if (StringUtils.isEmpty(esDiagram.getReleaseDiagramId())) {
            return false;
        }
        ESDiagram releaseEsDiagram = diagramApiClient.getEsDiagram(esDiagram.getReleaseDiagramId(), 1);
        // 没有发布过得数据不弹框
        if (releaseEsDiagram == null) {
            return false;
        }
        // 私有库和设计库版本一致不弹框
        return !Objects.equals(esDiagram.getReleaseVersion(), releaseEsDiagram.getReleaseVersion());
        // 弹框
    }

    @Override
    public List<EamReleaseHistoryDTO> queryReleaseHistory(String id, Boolean historyFlag) {
        List<ESDiagram> diagrams = diagramApiClient.selectByIds(Collections.singletonList(id), null, null);
        if (BinaryUtils.isEmpty(diagrams)) {
            return Collections.emptyList();
        }
        ESDiagram currDiagram = diagrams.get(0);
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
        eamDiagramQuery.setIsOpen(1);
        eamDiagramQuery.setReleaseDiagramId(currDiagram.getReleaseDiagramId());
        if (BinaryUtils.isEmpty(eamDiagramQuery.getReleaseDiagramId())) {
            eamDiagramQuery.setReleaseDiagramId(id);
        }
        List<ESDiagram> listByCdt = esDiagramDao.getListByCdt(eamDiagramQuery);
        if (BinaryUtils.isEmpty(listByCdt)) {
            return Collections.emptyList();
        }
        //查询视图全量信息
        List<Long> ids = listByCdt.stream().map(ESDiagram::getId).distinct().collect(Collectors.toList());
        List<ESDiagramDTO> diagramList = diagramApiClient.queryFullDiagramByIds(ids);
        if (CollectionUtils.isEmpty(diagramList)) {
            return Collections.emptyList();
        }
        diagramList.sort(Comparator.comparing(diagram -> diagram.getDiagram().getReleaseVersion()));
        List<EamReleaseHistoryDTO> historyList = new ArrayList<>();
        String[] userSet = diagramList.stream().map(ESDiagramDTO::getDiagram).map(ESDiagramInfoDTO::getOwnerCode).distinct().toArray(String[]::new);
        CSysUser userCdt = new CSysUser();
        userCdt.setDomainId(domainId);
        userCdt.setLoginCodes(userSet);
        userCdt.setSuperUserFlags(new Integer[]{0, 1});
        List<SysUser> cops = userApiSvc.getSysUserByCdt(userCdt);
        Map<String, SysUser> userMap = cops.stream().collect(Collectors.toMap(SysUser::getLoginCode, each -> each, (k1, k2) -> k1));
        for (ESDiagramDTO diagramInfo : diagramList) {
            ESDiagramInfoDTO diagram = diagramInfo.getDiagram();
            //目录切换到历史版本,视图历史只展示当时版本以前的版本信息
            if(historyFlag && diagram.getReleaseVersion()>currDiagram.getReleaseVersion()){
                continue;
            }
            EamReleaseHistoryDTO history = new EamReleaseHistoryDTO();
            history.setReleaseUser(userMap.get(diagram.getOwnerCode()));
            EamDiagramRelease releaseInfo = new EamDiagramRelease();
            diagram.setCreator(diagram.getCreator());
            diagram.setOwnerCode(diagram.getOwnerCode());
            releaseInfo.setDiagram(diagram);
            releaseInfo.setCreateTime(diagram.getOpenTime());
            releaseInfo.setVersionNo(diagramList.size()==1?1:diagram.getReleaseVersion());
            releaseInfo.setDEnergy(diagram.getDEnergy());
            if (!StringUtils.isEmpty(diagram.getReleaseDesc())) {
                releaseInfo.setReleaseDesc(diagram.getReleaseDesc());
            }
            history.setReleaseInfo(releaseInfo);
            historyList.add(history);
        }
        return historyList;
    }

    /**
     * 根据分类名称查询分类IDF
     */
    private Long getClassIdByName(String className) {
        CCcCiClass cCcCiClass = new CCcCiClass();
        cCcCiClass.setClassNameEqual(className);
        List<CcCiClassInfo> resultList = iciClassApiSvc.queryCiClassInfoList(1L, cCcCiClass, null, false);
        if (CollectionUtils.isEmpty(resultList)) {
            return null;
        }
        return resultList.get(0).getCiClass().getId();
    }


    @Override
    public List<CcCiRltInfo> getActivityListByTaskRlt(String diagramId, String ciCode, String libType) {
        JSONObject componentConfig = bmConfigSvc.getBusComponentConfig();
        if (BinaryUtils.isEmpty(componentConfig)) {
            throw new ServiceException("缺少业务组件相关配置:BUS_COMPONENT_CONFIG,请添加！");
        }
        ESDiagram esDiagram = diagramApiClient.getEsDiagram(diagramId, LibType.PRIVATE.name().equals(libType) ? 0 : 1);
        String viewType = esDiagram.getViewType();
        ElementDto elementDto = new ElementDto();
        elementDto.setType(3);
        elementDto.setArtifactId(Long.valueOf(viewType));
        List<EamArtifactElementVo> artifactElementRlt = artifactSvc.queryAllColumns(elementDto);
        if (BinaryUtils.isEmpty(artifactElementRlt)) {
            throw new ServiceException("该视图关联制品关系类型不存在");
        }
        ESCISearchBean bean = new ESCISearchBean();
        bean.setCiCodes(Lists.newArrayList(ciCode));
        Page<ESCIInfo> taskCiPage = ciSwitchSvc.searchESCIByBean(bean, LibType.DESIGN);
        if (BinaryUtils.isEmpty(taskCiPage.getData())) {
            throw new ServiceException("暂无数据！");
        }
        Long taskClassId = taskCiPage.getData().get(0).getClassId();
        //查询制品信息
        Long activityClassId = getClassIdByName(componentConfig.getString(Env.BM_ACTIVITY));

        Long rltClass = null;
        boolean existRlt = false;
        List<String> elements = artifactElementRlt.get(0).getElements();
        for (String element : elements) {
            JSONObject jsonObject = JSON.parseObject(element);
            String targetCiInfo = jsonObject.getString("targetCiInfo");
            if (targetCiInfo.contains(taskClassId.toString())) {
                String sourceCiInfo = jsonObject.getString("sourceCiInfo");
                if (activityClassId != null && sourceCiInfo.contains(activityClassId.toString())) {
                    existRlt = true;
                    String rltCiClass = jsonObject.getString("rltClassInfo");
                    JSONObject rltClassInfo = JSON.parseObject(rltCiClass);
                    rltClass = JSON.parseObject(rltClassInfo.getString("ciClass")).getLong("id");
                    break;
                }
            }
        }
        if (existRlt) {
            ESRltSearchBean rltSearchBean = new ESRltSearchBean();
            rltSearchBean.setSourceClassIds(Lists.newArrayList(activityClassId));
            rltSearchBean.setTargetCiCodes(Sets.newHashSet(ciCode));
            rltSearchBean.setRltClassIds(Lists.newArrayList(rltClass));
            Page<CcCiRltInfo> designPage = ciRltSwitchSvc.searchRltByBean(rltSearchBean, LibType.DESIGN);
            return designPage.getData();
        }
        return Collections.emptyList();
    }

    @Override
    public List<CheckBatchArtifactRuleVo> categoryEleNumCheckBatch(List<String> energyIds) {
        if(BinaryUtils.isEmpty(energyIds)){
            return Collections.emptyList();
        }
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        //根据视图id视图所在的模型树，再去校验模型树的层级配置是否完全。
        Long modelId = categorySvc.getModelIdByDiagramIds(energyIds, LibType.PRIVATE);
        if(BinaryUtils.isEmpty(modelId)){
            throw new BinaryException("当前模型关联模型工艺已删除,请联系管理员!");
        }
        EamMultiModelHierarchy modelTree = hierarchySvc.getModelById(modelId);
        if(BinaryUtils.isEmpty(modelTree) || modelTree.getDataStatus()==0){
            throw new BinaryException("当前模型关联模型工艺已删除,请联系管理员!");
        }
        if(modelTree.getReleaseState()==0){
            throw new BinaryException("当前模型关联模型工艺未发布,请联系管理员!");
        }
        List<EamHierarchyDto> hierarchyList = bmHierarchySvc.queryByModelId(modelId);
        if(BinaryUtils.isEmpty(hierarchyList)){
            throw new BinaryException("未查询到层级配置信息,请联系管理员!");
        }
        for (EamHierarchyDto dto : hierarchyList) {
            if(BinaryUtils.isEmpty(dto.getArtifactId())){
                throw new BinaryException(dto.getName()+"L"+dto.getDirLvl()+"层未关联制品,请联系管理员!");
            }
        }
        //查询所有视图信息
        List<ESDiagramDTO> diagramList = new ArrayList<>();
        try{
            Long[] diagramIds = diagramApiClient.queryDiagramInfoBydEnergy(energyIds.toArray(new String[]{}));
            diagramList = diagramApiClient.queryDiagramInfoByIds(diagramIds, null, false, false);
        }catch (Exception e){
            log.error(e.getMessage());
        }
        if(BinaryUtils.isEmpty(diagramList)){
            return Collections.emptyList();
        }
        List<Long> artifactIds = new ArrayList<>();
        List<Long> dirIds = new ArrayList<>();
        for (ESDiagramDTO diagramInfo : diagramList) {
            String viewType = diagramInfo.getDiagram().getViewType();
            if(!BinaryUtils.isEmpty(viewType)){
                artifactIds.add(Long.parseLong(viewType));
            }
            Long dirId = diagramInfo.getDiagram().getDirId();
            if(!BinaryUtils.isEmpty(dirId)){
                dirIds.add(dirId);
            }
        }
        if(BinaryUtils.isEmpty(artifactIds)){
            return Collections.emptyList();
        }
        List<EamCategory> categorys = categorySvc.getByIds(dirIds, LibType.PRIVATE);
        Map<Long, String> dirNameMap = categorys.stream().collect(Collectors.toMap(EamCategory::getId, EamCategory::getDirName, (k1,k2)->k2));
        //取出所有视图信息中的node节点
        List<ESDiagramModel> modelList = diagramList.stream().map(each -> each.getDiagram().getModelList()).flatMap(Collection::stream).collect(Collectors.toList());
        //视图中没有拖入分类 getNodeDataArray
        List<ESDiagramNode> nodeList = modelList.stream().map(ESDiagramModel::getNodeDataArray).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList());
        Map<String, List<ESDiagramNode>> nodeGroup = nodeList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(ESDiagramNode::getdEnergy));
        //查询所有制品ci分栏信息
        List<Integer> types = Lists.newArrayList(ArtifactType.CI_TYPE.val(), ArtifactType.ASSET_TYPE.val());
        Map<Long, List<EamArtifactElement>> artifactMap = artifactSvc.queryByIdsAndType(artifactIds, types);
        Map<Long, List<ArtifactConstraintVo>> artifactClassMap = getArtifactClassNum(artifactMap);
        //校验
        List<CheckBatchArtifactRuleVo> result = new ArrayList<>();
        for (ESDiagramDTO diagramInfo : diagramList) {
            String dEnergy = diagramInfo.getDiagram().getDEnergy();
            CheckBatchArtifactRuleVo rule = new CheckBatchArtifactRuleVo();
            rule.setDiagramName(diagramInfo.getDiagram().getName());
            rule.setDirName(dirNameMap.get(diagramInfo.getDiagram().getDirId()));
            String viewType = diagramInfo.getDiagram().getViewType();
            if(BinaryUtils.isEmpty(viewType)){
                continue;
            }
            Long artifactId = Long.parseLong(viewType);
            if(BinaryUtils.isEmpty(artifactMap.get(artifactId))){
                throw new BinaryException("视图'"+diagramInfo.getDiagram().getName()+"'制品已被删除/取消发布!");
            }
            List<ArtifactConstraintVo> numList = BinaryUtils.isEmpty(artifactClassMap.get(artifactId))?Lists.newArrayList() : artifactClassMap.get(artifactId);
            List<ESDiagramNode> nodes = BinaryUtils.isEmpty(nodeGroup.get(dEnergy)) ? Lists.newArrayList() : nodeGroup.get(dEnergy);
            String info = getArtifactCheckInfo(numList, nodes);
            if(BinaryUtils.isEmpty(info)){
                continue;
            }
            rule.setMessage(info);
            result.add(rule);
        }
        return result;
    }

    @Override
    public Integer updateArtifactId(Set<String> diagramIds, Long artifactId) {
        Map<String, Object> params = new HashMap<>(16);
        params.put("viewType", artifactId.toString());
        boolean suc = esDiagramDao.updateByQuery(QueryBuilders.termsQuery("dEnergy.keyword", diagramIds), "ctx._source.viewType=params.viewType;", true, params);
        return suc?1:0;
    }

    private String getArtifactCheckInfo(List<ArtifactConstraintVo> numList, List<ESDiagramNode> nodes){
        Map<String, Integer> shapeGroup = new HashMap<>(16);
        for (ESDiagramNode node : nodes) {
            if(BinaryUtils.isEmpty(node.getNodeJson())){
                continue;
            }
            JSONObject nodeJson = JSON.parseObject(node.getNodeJson());
            String nodeKey = nodeJson.getString("classId");
            if(BinaryUtils.isEmpty(nodeKey)){
                nodeKey = nodeJson.getString("id");
                if(BinaryUtils.isEmpty(nodeKey)){
                    continue;
                }
            }
            shapeGroup.compute(nodeKey, (key, value)-> BinaryUtils.isEmpty(value)?1:++value);
        }
        StringBuilder info = new StringBuilder();
        for (ArtifactConstraintVo constraint : numList) {
            String key = constraint.getKey();
            Integer viewNum = constraint.getViewNumber();
            Integer num = BinaryUtils.isEmpty(shapeGroup.get(key)) ? 0 : shapeGroup.get(key);
            if (constraint.getRelation().equals(ArtifactRelation.EQUALS.val()) && !num.equals(viewNum)) {
                info.append(constraint.getLabelName()).append("的实例个数必须为").append(viewNum).append("\n");
            } else if (constraint.getRelation().equals(ArtifactRelation.GREAT.val()) && num < viewNum) {
                info.append(constraint.getLabelName()).append("的实例个数必须大于或等于").append(viewNum).append("\n");
            } else if (constraint.getRelation().equals(ArtifactRelation.LESS.val()) && num > viewNum) {
                info.append(constraint.getLabelName()).append("的实例个数必须小于或等于").append(viewNum).append("\n");
            }
        }
        return info.toString();
    }

    /**
     * 组装每个制品分栏中架构分类限制条件
     * @param artifactMap 制品map
     * @return Map<制品id, 分类数量限制信息>
     */
    private Map<Long, List<ArtifactConstraintVo>> getArtifactClassNum(Map<Long, List<EamArtifactElement>> artifactMap){
        Map<Long, List<ArtifactConstraintVo>> result = new HashMap<>(16);
        for (Map.Entry<Long, List<EamArtifactElement>> artifact : artifactMap.entrySet()) {
            List<EamArtifactElement> columns = artifact.getValue();
            List<ArtifactConstraintVo> numList = new ArrayList<>();
            List<String> elements = columns.stream().map(EamArtifactElement::getElements).flatMap(Collection::stream).collect(Collectors.toList());
            Map<String, EamArtifactCiVo> artifactCiMap = elements.stream().map(s -> JSON.parseObject(s, EamArtifactCiVo.class)).collect(Collectors.toMap(EamArtifactCiVo::getId, each->each,(k1,k2)->k2));
            for (EamArtifactCiVo vo : artifactCiMap.values()) {
                ArtifactConstraintVo constraint = new ArtifactConstraintVo();
                constraint.setKey(vo.getId());
                constraint.setLabelName(vo.getViewName());
                constraint.setRelation(vo.getRelation());
                constraint.setViewNumber(vo.getViewNumber());
                numList.add(constraint);
            }
            result.put(artifact.getKey(), numList);
        }
        return result;
    }

    @Override
    public List<CheckAssertEditRes> checkAssertEditAuth(CheckAssertEditReq req, Boolean fromImport) {
        CheckAssertEditParam param = prepareCheckAssert(req);
        List<CheckAssertEditRes> resList = new ArrayList<>();
        for (CheckAssertEditCiParam ciParam : req.getCiParams()) {
            CheckAssertEditRes res = new CheckAssertEditRes();
            res.setCiPrimaryKey(ciParam.getCiPrimaryKey());
            res.setCiCode(ciParam.getCiCode());
            res.setLibType(ciParam.getLibType());
            wapperRes(res, param, fromImport);
            resList.add(res);
        }
        return resList;
    }

    private CheckAssertEditParam prepareCheckAssert(CheckAssertEditReq req) {
        Assert.notNull(req, "参数不能为空");
        Assert.notNull(req.getFromDiagram(), "是否来源于视图不能为空");
        Assert.notNull(req.getOperator(), "操作人不能为空");
        List<CheckAssertEditCiParam> ciParams = req.getCiParams();
        if (CollectionUtils.isEmpty(ciParams)) {
            throw new BinaryException("ci主键列表不能为空");
        }
        for (CheckAssertEditCiParam param : ciParams) {
            Assert.notNull(param.getCiPrimaryKey(), "ci主键不能为空");
            Assert.notNull(param.getCiCode(), "ciCode不能为空");
            Assert.notNull(param.getLibType(), "数据来源不能为空");
        }
        Map<LibType, List<CheckAssertEditCiParam>> params = ciParams.stream().collect(Collectors.groupingBy(CheckAssertEditCiParam::getLibType));
        Set<String> owners = new HashSet<>();
        Map<String, ESCIInfo> curPrivateCiPrimaryKeyMap = getKeyCiInfo(params, true, LibType.PRIVATE, owners, req.getOperator());
        Map<String, ESCIInfo> curPrivateCiCodeMap = getKeyCiInfo(params, false, LibType.PRIVATE, owners, req.getOperator());
        Map<String, ESCIInfo> privateDesignSamePrimaryKeyMap = getSameKeyMap(curPrivateCiPrimaryKeyMap, true, owners, req.getOperator());
        Map<String, ESCIInfo> privateDesignSameCiCodeMap = getSameKeyMap(curPrivateCiCodeMap, false, owners, req.getOperator());
        Map<String, ESCIInfo> designCiPrimaryKeyMap = getKeyCiInfo(params, true, LibType.DESIGN, owners, req.getOperator());
        Map<String, ESCIInfo> designCiCodeMap = getKeyCiInfo(params, false, LibType.DESIGN, owners, req.getOperator());
        Map<String, ESCIInfo> importDesignSamePrimaryKeyMap = new HashMap<>();
        Map<String, ESCIInfo> importDesignSameCiCodeMap = new HashMap<>();
        if (Boolean.FALSE.equals(req.getFromDiagram())) {
            importDesignSamePrimaryKeyMap = getKeyCiInfo(params.get(LibType.PRIVATE), true, LibType.DESIGN, owners, req.getOperator());
            importDesignSameCiCodeMap = getKeyCiInfo(params.get(LibType.PRIVATE), false, LibType.DESIGN, owners, req.getOperator());
        }
        Map<String, SysUser> userMap = new ConcurrentHashMap<>();
        SysUser adminUser = userApiSvc.getSingleUserByRoleName("admin");
        if (!CollectionUtils.isEmpty(owners)) {
            CSysUser cdt = new CSysUser();
            cdt.setLoginCodes(owners.toArray(new String[owners.size()]));
            List<SysUser> sysUsers = userApiSvc.getSysUserByCdt(cdt);
            if (!CollectionUtils.isEmpty(sysUsers)) {
                userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getLoginCode, Function.identity()));
            }
        }
        boolean operatorAdmin = false;
        UserInfo operatorInfo = userApiSvc.getUserInfoByLoginCode(req.getOperator());
        if (!CollectionUtils.isEmpty(operatorInfo.getRoles())) {
            List<SysRole> adminRoles = operatorInfo.getRoles().stream().filter(
                    role -> "admin".equals(role.getRoleName())).collect(Collectors.toList());
            operatorAdmin = !CollectionUtils.isEmpty(adminRoles);
        }
        return CheckAssertEditParam.builder()
                .fromDiagram(req.getFromDiagram())
                .curPrivateCiPrimaryKeyMap(curPrivateCiPrimaryKeyMap)
                .curPrivateCiCodeMap(curPrivateCiCodeMap)
                .designCiCodeMap(designCiCodeMap)
                .privateDesignSamePrimaryKeyMap(privateDesignSamePrimaryKeyMap)
                .privateDesignSameCiCodeMap(privateDesignSameCiCodeMap)
                .designCiPrimaryKeyMap(designCiPrimaryKeyMap)
                .designCiCodeMap(designCiCodeMap)
                .importDesignSamePrimaryKeyMap(importDesignSamePrimaryKeyMap)
                .importDesignSameCiCodeMap(importDesignSameCiCodeMap)
                .userMap(userMap)
                .admin(adminUser)
                .operator(req.getOperator())
                .operatorInfo(operatorInfo).operatorAdmin(operatorAdmin)
                .ownerDefMap(getOwnerDefs())
                .build();
    }

    private void wapperRes(CheckAssertEditRes res, CheckAssertEditParam param, Boolean fromImport) {
        if (LibType.PRIVATE.equals(res.getLibType())) {
            setPrivateRes(res, param, fromImport);
            return;
        }
        setDesignRes(res, param, false, fromImport);
    }

    private void setPrivateRes(CheckAssertEditRes res, CheckAssertEditParam param, Boolean fromImport) {
        //私有库没查到当前资产且非导入
        if (!param.getCurPrivateCiPrimaryKeyMap().containsKey(res.getCiPrimaryKey())
                && !param.getCurPrivateCiCodeMap().containsKey(res.getCiCode()) && !fromImport) {
            //我的数据那编辑
            if (!param.getFromDiagram()) {
                log.error("未查到私有库数据,params[{}]", JSON.toJSONString(res));
                //throw new BinaryException("数据未查到，请刷新列表重试");
                res.setEdit(false);
                return;
            }
            //画布普通形状
            res.setEdit(true);
            return;
        }
        setDesignRes(res, param, true, fromImport);
    }

    private void setDesignRes(CheckAssertEditRes res, CheckAssertEditParam param, Boolean sameKey, Boolean fromImport) {
        Map<String, ESCIInfo> primaryKeyMap = getPrimaryKeyMap(param, sameKey, fromImport);
        Map<String, ESCIInfo> ciCodeMap = getCiCodeMap(param, sameKey, fromImport);
        //设计库没查到当前资产
        if (!primaryKeyMap.containsKey(res.getCiPrimaryKey())
                && !ciCodeMap.containsKey(res.getCiCode())) {
            res.setEdit(true);
            return;
        }
        ESCIInfo designCiInfo = primaryKeyMap.get(res.getCiPrimaryKey());
        if (designCiInfo == null) {
            designCiInfo = ciCodeMap.get(res.getCiCode());
        }
        String ciOwnerCode = designCiInfo.getOwnerCode();
        //不在资产编辑权限配置里
        if (BinaryUtils.isEmpty(param.getOwnerDefMap())
                || !param.getOwnerDefMap().containsKey(designCiInfo.getClassId())) {
            res.setEdit(true);
            return;
        }
        //资产负责人
        Set<String> owners = new HashSet<>();
        //资产"负责人"字段名称
        List<String> ownerDefs = param.getOwnerDefMap().get(designCiInfo.getClassId());
        if (!CollectionUtils.isEmpty(ownerDefs)) {
            for (String ownerDef : ownerDefs) {
                Object owner = designCiInfo.getAttrs().get(ownerDef);
                if (owner == null) {
                    continue;
                }
                List<String> loginCodes = this.analysisLoginCode(owner.toString());
                if (!CollectionUtils.isEmpty(loginCodes)) {
                    owners.addAll(loginCodes);
                }
            }
        }

        //资产创建人或admin角色用户或资产负责人
        res.setEdit(param.getOperator().equals(ciOwnerCode) || param.getOperatorAdmin() || owners.contains(param.getOperator()));
        if (!res.getEdit()) {
            res.setSameKeyDesignCiInfo(designCiInfo);
        }
        if (StringUtils.isBlank(ciOwnerCode)) {
            ciOwnerCode = "";
        }
        setCiCreator(res, param.getUserMap().getOrDefault(ciOwnerCode, param.getAdmin()));
    }

    private List<String> analysisLoginCode(String data) {
        if (org.apache.commons.lang3.StringUtils.isBlank(data) || data.equals("null")) {
            return new ArrayList<>();
        }
        try {
            List<SysUser> users = JSON.parseArray(data, SysUser.class);
            return users.stream().map(SysUser::getLoginCode).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("人员数据解析异常:{}", data);
        }
        return new ArrayList<>();
    }

    private Map<String, ESCIInfo> getPrimaryKeyMap(CheckAssertEditParam param, Boolean sameKey, Boolean fromImport) {
        if (fromImport) {
            return param.getImportDesignSamePrimaryKeyMap();
        }
        if (sameKey) {
            return param.getPrivateDesignSamePrimaryKeyMap();
        }
        return param.getDesignCiPrimaryKeyMap();
    }

    private Map<String, ESCIInfo> getCiCodeMap(CheckAssertEditParam param, Boolean sameKey, Boolean fromImport) {
        if (fromImport) {
            return param.getImportDesignSameCiCodeMap();
        }
        if (sameKey) {
            return param.getPrivateDesignSameCiCodeMap();
        }
        return param.getDesignCiCodeMap();
    }

    private void setCiCreator(CheckAssertEditRes res, SysUser user) {
        res.setCreator(user.getLoginCode());
        res.setCreatorName(user.getUserName());
    }

    private Map<String, ESCIInfo> getSameKeyMap(Map<String, ESCIInfo> keyMap, Boolean ciPrimaryKey, Set<String> owners, String operator) {
        if (org.springframework.util.CollectionUtils.isEmpty(keyMap)) {
            return new ConcurrentHashMap<>();
        }
        List<CheckAssertEditCiParam> ciParams = new ArrayList<>();
        for (Map.Entry<String, ESCIInfo> entry : keyMap.entrySet()) {
            CheckAssertEditCiParam ciParam = new CheckAssertEditCiParam();
            if (ciPrimaryKey) {
                ciParam.setCiPrimaryKey(entry.getKey());
            } else {
                ciParam.setCiCode(entry.getKey());
            }
            ciParams.add(ciParam);
        }
        Map<LibType, List<CheckAssertEditCiParam>> params = new ConcurrentHashMap<>();
        params.put(LibType.DESIGN, ciParams);
        return getKeyCiInfo(params, ciPrimaryKey, LibType.DESIGN, owners, operator);
    }

    private Map<String, ESCIInfo> getKeyCiInfo(List<CheckAssertEditCiParam> params
            , Boolean ciPrimaryKey, LibType libType, Set<String> owners, String operator) {
        if (org.springframework.util.CollectionUtils.isEmpty(params)) {
            return new ConcurrentHashMap<>();
        }
        if (ciPrimaryKey) {
            List<String> ciPrimaryKeys = params.stream().map(CheckAssertEditCiParam::getCiPrimaryKey).distinct().collect(Collectors.toList());
            List<ESCIInfo> ciInfos = queryByCiPrimaryKeys(ciPrimaryKeys, operator, libType);
            setCiOwners(ciInfos, owners);
            return ciInfos.stream().collect(Collectors.toMap(ESCIInfo::getCiPrimaryKey, Function.identity(), (k1,k2) -> k1));
        }
        List<String> ciCodes = params.stream().map(CheckAssertEditCiParam::getCiCode).distinct().collect(Collectors.toList());
        List<ESCIInfo> ciInfos = queryByCiCodes(ciCodes, operator, libType);
        setCiOwners(ciInfos, owners);
        return ciInfos.stream().collect(Collectors.toMap(ESCIInfo::getCiCode, Function.identity(), (k1,k2) -> k1));
    }

    private Map<String, ESCIInfo> getKeyCiInfo(Map<LibType, List<CheckAssertEditCiParam>> params
            , Boolean ciPrimaryKey, LibType libType, Set<String> owners, String operator) {
        List<CheckAssertEditCiParam> reqs = params.get(libType);
        if (org.springframework.util.CollectionUtils.isEmpty(reqs)) {
            return new ConcurrentHashMap<>();
        }
        if (ciPrimaryKey) {
            List<String> ciPrimaryKeys = reqs.stream().map(CheckAssertEditCiParam::getCiPrimaryKey).distinct().collect(Collectors.toList());
            List<ESCIInfo> ciInfos = queryByCiPrimaryKeys(ciPrimaryKeys, operator, libType);
            setCiOwners(ciInfos, owners);
            return ciInfos.stream().collect(Collectors.toMap(ESCIInfo::getCiPrimaryKey, Function.identity(), (k1,k2) -> k1));
        }
        List<String> ciCodes = reqs.stream().map(CheckAssertEditCiParam::getCiCode).distinct().collect(Collectors.toList());
        List<ESCIInfo> ciInfos = queryByCiCodes(ciCodes, operator, libType);
        setCiOwners(ciInfos, owners);
        return ciInfos.stream().collect(Collectors.toMap(ESCIInfo::getCiCode, Function.identity(), (k1,k2) -> k1));
    }

    private void setCiOwners(List<ESCIInfo> ciInfos, Set<String> owners) {
        if (org.springframework.util.CollectionUtils.isEmpty(ciInfos)) {
            return;
        }
        Set<String> curOwners = ciInfos.stream().map(ESCIInfo::getOwnerCode).filter(Objects::nonNull).collect(Collectors.toSet());
        if (org.springframework.util.CollectionUtils.isEmpty(curOwners)) {
            return;
        }
        owners.addAll(curOwners);
    }

    private List<ESCIInfo> queryByCiCodes(List<String> ciCodes, String ownerCode, LibType libType) {
        if (CollectionUtils.isEmpty(ciCodes)) {
            return new ArrayList<>();
        }
        CCcCi cdt = new CCcCi();
        cdt.setCiCodes(ciCodes.toArray(new String[ciCodes.size()]));
        // 设置ownerCode 查询条件 查询私有库数据
        cdt.setOwnerCodeEqual(ownerCode);
        List<CcCiInfo> ciInfos = ciSwitchSvc.queryCiInfoList(1L, cdt, null, Boolean.FALSE, Boolean.TRUE, libType);
        return EamUtil.coverCiInfoList(ciInfos);
    }

    private List<ESCIInfo> queryByCiPrimaryKeys(List<String> ciPrimaryKeys, String ownerCode, LibType libType) {
        if (CollectionUtils.isEmpty(ciPrimaryKeys)) {
            return new ArrayList<>();
        }
        List<List<String>> queryCiPrimaryKeys = new ArrayList<>();
        ciPrimaryKeys.forEach(keys -> {
            queryCiPrimaryKeys.add(JSONArray.parseArray(keys, String.class));
        });
        if (LibType.PRIVATE.equals(libType)) {
            for (List<String> ciPrimaryKey : queryCiPrimaryKeys) {
                ciPrimaryKey.add(ownerCode);
            }
        }
        List<CcCiInfo> ciInfos = ciSwitchSvc.getCIInfoListByCIPrimaryKeys(1L, queryCiPrimaryKeys, libType);
        return EamUtil.coverCiInfoList(ciInfos);
    }

    private Map<Long, List<String>> getOwnerDefs() {
        String confStr = bmConfigSvc.getConfigType("AXEA_CONFIG");
        if (StringUtils.isBlank(confStr)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        JSONObject conf = JSON.parseObject(confStr);
        String assertAuthChecksStr = conf.getString("assertAuthChecks");
        if (StringUtils.isBlank(assertAuthChecksStr)) {
            log.error("需要进行系统文件夹创建的分类配置为空");
            return new HashMap<>();
        }
        List<String> authCiClassCodes = JSONObject.parseArray(assertAuthChecksStr, String.class);
        if (CollectionUtils.isEmpty(authCiClassCodes)) {
            log.error("需要进行系统文件夹创建的分类配置为空");
            return new HashMap<>();
        }

        String classConfStr = conf.getString("classConf");
        if (StringUtils.isBlank(classConfStr)) {
            log.error("分类配置为空");
            return new HashMap<>();
        }
        Map<String, Long> authCiClassMap = new HashMap<>();
        CCcCiClass cdt = new CCcCiClass();
        cdt.setClassCodes(authCiClassCodes.toArray(new String[authCiClassCodes.size()]));
        List<CcCiClassInfo> ciClassInfos = iciClassApiSvc.queryClassByCdt(cdt);
        if (!CollectionUtils.isEmpty(ciClassInfos)) {
            authCiClassMap = ciClassInfos.stream().map(CcCiClassInfo::getCiClass).collect(Collectors.toMap(CcCiClass::getClassCode, CcCiClass::getId));
        }

        JSONObject classConf = JSONObject.parseObject(classConfStr);
        Map<Long, List<String>> ownerDefMap = new HashMap<>();
        for (String authCiClassCode : authCiClassCodes) {
            if (!authCiClassMap.containsKey(authCiClassCode)) {
                continue;
            }
            Long authCiClassId = authCiClassMap.get(authCiClassCode);
            ownerDefMap.put(authCiClassId, new ArrayList<>());

            String ciClassConfDetailStr = classConf.getString(authCiClassCode);
            if (StringUtils.isBlank(ciClassConfDetailStr)) {
                continue;
            }
            JSONObject ciClassConfDetail = JSONObject.parseObject(ciClassConfDetailStr);
            String ownerDefsStr = ciClassConfDetail.getString("ownerDefs");
            if (StringUtils.isBlank(ownerDefsStr)) {
                continue;
            }
            List<String> ownerDefs = JSONObject.parseArray(ownerDefsStr, String.class);
            if (!CollectionUtils.isEmpty(ownerDefs)) {
                ownerDefMap.put(authCiClassId, ownerDefs);
            }
        }
        return ownerDefMap;
    }
}

